package main
 
import (
	"fmt"
	"net/http"
	"strings"
	"github.com/gorilla/mux"
)
 
/*
1、Token的引入：Token是在客户端频繁向服务端请求数据，服务端频繁的去数据库查询用户名和密码并进行对比，判断用户名和密码正确与否，并作出相应提示，在这样的背景下，Token便应运而生。

2、Token的定义：Token是服务端生成的一串字符串，以作客户端进行请求的一个令牌，当第一次登录后，服务器生成一个Token便将此Token返回给客户端，以后客户端只需带上这个Token前来请求数据即可，无需再次带上用户名和密码。

3、使用Token的目的：Token的目的是为了减轻服务器的压力，减少频繁的查询数据库，使服务器更加健壮。
*/
type authMiddleware struct {
	tokenUsers map[string]string
}
 
func (amw *authMiddleware) Populate() {
	amw.tokenUsers = make(map[string]string)
	amw.tokenUsers["000"] = "user0"
	amw.tokenUsers["aaa"] = "userA"
	amw.tokenUsers["05ft"] = "randomUser"
	amw.tokenUsers["deadbeef"] = "user0"
}
 
func (amw *authMiddleware) Middleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		token := strings.Trim(r.Header.Get("X-Session-Token"), " ")
		if token == "" {
			fmt.Fprintf(w, "token is error \r\n")
		}
 
		if user, found := amw.tokenUsers[token]; found {
			//we found the token in out map
			fmt.Printf("Authenticated user: %s\n", user)
			fmt.Fprintf(w, "Authenticated user: %s\n", user)
			// Pass down the request to the next middleware (or final handler)
			next.ServeHTTP(w, r)
		} else {
			// Write an error and stop the handler chain
			http.Error(w, "Forbidden", http.StatusForbidden)
		}
	})
}
 
func main() {
	r := mux.NewRouter()
	r.HandleFunc("/", handler)
 
	amw := authMiddleware{}
	amw.Populate()
 
	r.Use(amw.Middleware)
 
	http.ListenAndServe(":8080", r)
}
 
func handler(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("handler"))
}
